package com.kexio.auth.config;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.kexio.auth.aop.LoggingAspect;
import com.kexio.auth.aop.PerformanceMonitorAspect;
import com.kexio.auth.metrics.UnifiedNoopMetricsProvider;
import com.kexio.auth.security.PasswordEncoder;
import com.kexio.auth.web.GlobalExceptionHandler;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;

/**
 * Kexio权限框架自动配置类
 * 
 * 负责自动装配权限管理相关的核心组件：
 * - JWT令牌提供者
 * - 密码编码器
 * - 安全上下文管理
 * - 权限验证切面
 * - 数据权限拦截器
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@AutoConfiguration
@EnableConfigurationProperties({SecurityProperties.class, MybatisPlusProperties.class, TenantModeProperties.class})
@ComponentScan(basePackages = "com.kexio.auth")
@ConditionalOnProperty(prefix = "kexio.auth", name = "enabled", havingValue = "true", matchIfMissing = true)
public class AuthAutoConfiguration {
    
    private static final Logger logger = LoggerFactory.getLogger(AuthAutoConfiguration.class);
    
    public AuthAutoConfiguration() {
        logger.info("Kexio权限框架自动配置开始加载...");
    }
    
    // ==================== Sa-Token核心配置 ====================
    
    // Sa-Token 1.44.0 自带Spring Boot 3支持，无需自定义SaTokenContext
    
    // Sa-Token拦截器已在SaTokenConfiguration中配置，这里不再重复注册
    // 避免双重拦截器配置导致的冲突和安全漏洞
    
    // ==================== 核心安全组件 ====================
    
    /**
     * 密码编码器
     */
    @Bean
    @ConditionalOnMissingBean
    public PasswordEncoder passwordEncoder() {
        logger.info("注册密码编码器");
        return new PasswordEncoder();
    }
    
    
    
    // ==================== 安全过滤器配置 ====================
    
    /**
     * Web安全配置
     */
    @Configuration
    @ConditionalOnProperty(prefix = "kexio.auth.web", name = "enabled", havingValue = "true", matchIfMissing = true)
    static class WebSecurityConfiguration implements WebMvcConfigurer {
        
        /**
         * 注册拦截器
         * 
         * 注意：Sa-Token拦截器由SaTokenConfiguration统一管理，避免重复注册
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            logger.info("Web安全配置：Sa-Token拦截器由SaTokenConfiguration统一管理");
            // Sa-Token拦截器已在SaTokenConfiguration中注册，此处不重复注册
        }
        
        /**
         * CORS配置源
         */
        @Bean
        @ConditionalOnMissingBean(name = "authCorsConfigurationSource")
        public org.springframework.web.cors.CorsConfigurationSource authCorsConfigurationSource() {
            org.springframework.web.cors.CorsConfiguration configuration = new org.springframework.web.cors.CorsConfiguration();
            
            // 允许的域名
            configuration.setAllowedOriginPatterns(Arrays.asList("*"));
            
            // 允许的HTTP方法
            configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"));
            
            // 允许的请求头
            configuration.setAllowedHeaders(Arrays.asList("*"));
            
            // 允许携带凭证
            configuration.setAllowCredentials(true);
            
            // 预检请求缓存时间（秒）
            configuration.setMaxAge(3600L);
            
            // 暴露的响应头
            configuration.setExposedHeaders(Arrays.asList(
                "Authorization", 
                "X-Total-Count", 
                "X-Tenant-Id",
                "X-Request-Id"
            ));
            
            org.springframework.web.cors.UrlBasedCorsConfigurationSource source = 
                new org.springframework.web.cors.UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", configuration);
            
            return source;
        }
        
        


        /**
         * 统一安全指标实现
         */
        @Bean
        @ConditionalOnMissingBean(com.kexio.auth.metrics.UnifiedSecurityMetrics.class)
        public com.kexio.auth.metrics.UnifiedSecurityMetrics unifiedSecurityMetrics() {
            logger.info("注册统一安全指标实现: UnifiedNoopMetricsProvider");
            return new UnifiedNoopMetricsProvider();
        }
        
        
        /**
         * 全局异常解析器（零注解）
         */
        @Bean
        @ConditionalOnMissingBean
        public org.springframework.web.servlet.HandlerExceptionResolver globalExceptionResolver() {
            logger.info("注册全局异常解析器: GlobalExceptionHandler");
            return new GlobalExceptionHandler();
        }
        
    }
    
    // ==================== MyBatis拦截器配置 ====================
    
    /**
     * MyBatis数据权限拦截器配置
     */
    @Configuration
    @ConditionalOnProperty(prefix = "kexio.auth.data-scope", name = "enabled", havingValue = "true", matchIfMissing = true)
    static class MyBatisConfiguration {
        
        // 数据权限拦截器配置已迁移到 SmartMybatisPlusAutoConfiguration 中统一管理
        // 新的配置提供更灵活的配置选项和更好的执行顺序控制
    }
    
    // ==================== AOP切面配置 ====================
    
    /**
     * AOP切面配置
     */
    @Configuration
    @ConditionalOnProperty(prefix = "kexio.auth.aop", name = "enabled", havingValue = "true", matchIfMissing = true)
    static class AopConfiguration {
        
        
        /**
         * 性能监控切面
         */
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(prefix = "kexio.auth.aop.performance", name = "enabled", havingValue = "true")
        public PerformanceMonitorAspect performanceMonitorAspect() {
            logger.info("注册性能监控切面: PerformanceMonitorAspect");
            return new PerformanceMonitorAspect();
        }
        
        /**
         * 日志记录切面
         */
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(prefix = "kexio.auth.aop.logging", name = "enabled", havingValue = "true", matchIfMissing = true)
        public LoggingAspect loggingAspect() {
            logger.info("注册日志记录切面: LoggingAspect");
            return new LoggingAspect();
        }
        
        // ❌ 已删除 ExceptionHandlingAspect
        // 原因：避免重复记录异常日志（与 GlobalExceptionHandler 冲突）
        // 改为统一在 GlobalExceptionHandler 中处理所有异常
        
        // 简单权限检查切面已整合到 PermissionAspect 中，无需单独注册
        
        /**
         * 限流检查切面（@RateLimit）
         */
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(prefix = "kexio.auth.aop.rate-limit", name = "enabled", havingValue = "true", matchIfMissing = true)
        public com.kexio.auth.aspect.RateLimitAspect rateLimitAspect() {
            logger.info("注册限流检查切面: RateLimitAspect");
            return new com.kexio.auth.aspect.RateLimitAspect();
        }
        
        /**
         * 限流服务
         */
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(prefix = "kexio.auth.rate-limit", name = "enabled", havingValue = "true", matchIfMissing = true)
        public com.kexio.auth.service.RateLimitService rateLimitService() {
            logger.info("注册限流服务: RateLimitService");
            return new com.kexio.auth.service.RateLimitService();
        }
        
    }
    
    // ==================== MyBatis增强配置 ====================
    // 
    // MyBatis-Plus相关配置已迁移到 SmartMybatisPlusAutoConfiguration 中统一管理
    // 新的配置提供更灵活和智能的拦截器配置能力
    
    // ==================== 多租户配置 ====================
    
    /**
     * 多租户配置
     */
    @Configuration
    @ConditionalOnProperty(prefix = "kexio.auth.tenant", name = "enabled", havingValue = "true", matchIfMissing = false)
    static class TenantConfiguration {
        
        /**
         * 租户解析器
         * 
         * 负责从HTTP请求中解析租户ID，支持多种来源：
         * - JWT Token中的租户信息（最高优先级）
         * - HTTP请求头中的租户信息
         * - URL参数中的租户信息
         * - 子域名中的租户信息
         */
        @Bean
        @ConditionalOnMissingBean
        public com.kexio.auth.tenant.TenantResolver tenantResolver() {
            logger.info("注册租户解析器: DefaultTenantResolver");
            return new com.kexio.auth.tenant.DefaultTenantResolver();
        }
        
        /**
         * 租户Web过滤器
         * 
         * 在Web请求生命周期中管理租户上下文：
         * - 请求开始时设置租户上下文
         * - 请求结束时清理ThreadLocal
         */
        @Bean
        @ConditionalOnMissingBean
        public com.kexio.auth.filter.TenantWebFilter tenantWebFilter() {
            logger.info("注册租户Web过滤器: TenantWebFilter");
            return new com.kexio.auth.filter.TenantWebFilter();
        }
        
        /**
         * 租户感知的任务装饰器
         * 
         * 用于异步任务中传递租户上下文，支持：
         * - @Async 异步方法
         * - ThreadPoolTaskExecutor 线程池任务  
         * - CompletableFuture 异步编程
         */
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(prefix = "kexio.auth.tenant.async", name = "enabled", havingValue = "true", matchIfMissing = false)
        public com.kexio.auth.async.TenantAwareTaskDecorator tenantAwareTaskDecorator() {
            logger.info("注册租户感知任务装饰器: TenantAwareTaskDecorator");
            return com.kexio.auth.async.TenantAwareTaskDecorator.create();
        }
        
    }
    
    // ==================== 动态数据源配置 ====================
    
    /**
     * 动态数据源配置说明：
     * 
     * 动态数据源相关的Bean由 DynamicDataSourceConfig 类负责创建和管理，
     * 该配置类使用 @Configuration 注解，会被自动扫描并加载。
     * 
     * 包含的组件：
     * - DynamicDataSourceProperties: 数据源配置属性绑定
     * - DynamicRoutingDataSource: 动态路由数据源
     * - DynamicDataSourceManager: 运行时数据源管理器
     * - DataSourceConfigurationInfo: 配置信息监控Bean
     * 
     * 启用条件：kexio.auth.datasource.enabled=true (默认启用)
     */
    
    // ==================== 事件配置 ====================
    

    
    // ==================== 框架集成说明 ====================
    
    /**
     * 框架组件自动装配说明：
     * 
     * 1. 过滤器组件：
     *    - JwtAuthenticationFilter: 通过@Component自动注册，@Order(20)控制执行顺序
     * 
     * 2. 切面组件：
     *    - PermissionAspect: 通过@Component自动注册，@Order(100)控制执行顺序
     *    - DataScopeAspect: 通过@Component自动注册，@Order(200)控制执行顺序
     * 
     * 3. 上下文组件：
     *    - AuthContextUtils: 通过@Bean注册为单例
     *    - DataScopeContextHolder: 工具类，使用ThreadLocal，无需注册为Bean
     * 
     * 4. 安全组件：
     *    - PasswordEncoder: 通过@Bean注册为单例
     *    - AuthContextUtils: 通过@Bean注册为单例
     * 
     * 5. 缓存和版本控制组件：
     *    - UnifiedCacheService: 通过@Service自动注册，支持L1(Caffeine)+L2(Redis)，统一的缓存服务
     *    - PermissionVersionService: 通过@Service自动注册，提供版本控制机制
     * 
     * 6. 配置属性：
     *    - SecurityProperties: 通过@EnableConfigurationProperties自动绑定配置
     * 
     * 注意：所有组件都遵循Spring Boot自动配置最佳实践，
     *      支持通过配置属性启用/禁用相关功能
     */
}
        

